﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GameServer.Core;
using GameServer.Model;
using Summer;

namespace GameServer.Mgr
{
    /// <summary>
    /// Entity管理器
    /// </summary>
    public class EntityManager : Singleton<EntityManager>
    {
        private int index = 1;
        private Dictionary<int, Entity> AllEntities = new Dictionary<int, Entity>();
        private Dictionary<int, List<Entity>> SpaceEntitier = new Dictionary<int, List<Entity>>();

        //public Entity CreateEntity()
        //{
        //    lock (this)
        //    {
        //        var entity = new Entity(index++, Vector3Int.zero, Vector3Int.zero);
        //        AllEntities[entity.entityId] = entity;
        //        return entity;
        //    }
        //}

        public void AddEntity(int spaceId,Entity entity)
        {
            lock(this)
            {
                AllEntities[entity.entityId] = entity;
                if (!SpaceEntitier.ContainsKey(spaceId))
                {
                    SpaceEntitier[spaceId] = new List<Entity>();
                }
                SpaceEntitier[spaceId].Add(entity);
            }
        }
        public void RemoveEntity(int spaceId, Entity entity)
        {
            lock (this)
            {
                SpaceEntitier[spaceId].Remove(entity);
                AllEntities.Remove(entity.entityId);
            }
        }
        public Entity GeteEntity(int id)
        {
            return AllEntities.GetValueOrDefault(id,null);
        }
        public int NewEntityId
        {
            get {
                lock(this){
                    return index++; 
                }
            }
        }
        public void Update()
        {
            foreach (var item in AllEntities)
            {
                item.Value.Update();
            }
        }

        public List<T> GetEntityList<T>(int spaceId,Predicate<T> mach) where T : Entity
        {
            return SpaceEntitier[spaceId].OfType<T>().Where(entity=>mach.Invoke(entity)).ToList();
        }

        public T GetNearest<T>(int spaceId,Vector3Int center,float range) where T : Entity
        {
            Predicate<T> match = (e) => { return Vector3Int.Distance(center, e.Position) <= range; };
            var t=GetEntityList<T>(spaceId, match).OrderBy(e=> Vector3Int.Distance(center, e.Position)).FirstOrDefault();
            return t;
        }
        public List<Actor> RangeUnit(int spaceId, Vector3Int position, int range)
        {
            Predicate<Actor> match = (e) => {
                return Vector3Int.Distance(position, e.Position) <= range;
            };
            return EntityManager.Instance.GetEntityList(spaceId, match);
        }
        public List<ItemEntity> GetNearstItem(int spaceId, Vector3Int position, int range)
        {
            List<ItemEntity> itemEntities = new List<ItemEntity>();
            Space _space = SpaceManager.Instance.GetSpace(spaceId);
            foreach (var item in _space.ItemDict.Values)
            {
                if (Vector3Int.Distance(item.Pos, position) <= range)
                {
                    itemEntities.Add(item);
                }
            }
            if (itemEntities.Count > 0)
            {
                return itemEntities;
            }
            else
            {
                return null;
            }
        }
    }
}
